package io.github.eric.urpc.core.config;

import io.github.eric.urpc.core.conn.ConnectionListener;
import io.github.eric.urpc.core.rpc.RpcController;
import io.github.eric.urpc.core.util.PidUtil;
import io.netty.handler.logging.LogLevel;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

/**
 * 暴露给用户使用的配置类，变量均是可配置项
 */
public abstract class AbstractConfig implements Config {
    public static final String PROP_APPLICATION_NAME = "urpc.applicationName";
    public static final String PROP_APPLICATION_ID = "urpc.applicationId";
    public static final String PROP_SOCKET_BACKLOG = "urpc.socketBacklog";
    public static final String PROP_SOCKET_RECV_BUF_SIZE = "urpc.socketRecvBufSize";
    public static final String PROP_SOCKET_SEND_BUF_SIZE = "urpc.socketSendBufSize";
    public static final String PROP_FRAME_MAX_LENGTH = "urpc.frameMaxLength";
    public static final String PROP_NETTY_LOGGING_LEVEL = "urpc.nettyLoggingLevel";
    public static final String PROP_READ_TIMEOUT = "urpc.readTimeout";
    public static final String PROP_ORDERED = "urpc.ordered";

    public static final String DEFAULT_CURRENT_APPLICATION_ID = UUID.randomUUID().toString();
    public static final int DEFAULT_SOCKET_BACKLOG = 128;
    public static final int DEFAULT_SOCKET_RECV_BUF_SIZE = 65536;
    public static final int DEFAULT_SOCKET_SEND_BUF_SIZE = 65536;
    public static final int DEFAULT_FRAME_MAX_LENGTH = 64 * 1024;
    public static final int DEFAULT_READ_TIMEOUT = 30;
    static {
        String sysPid = System.getProperty("PID");
        if (sysPid == null || sysPid.isEmpty()) {
            sysPid = String.valueOf(PidUtil.getCurPid());
            System.getProperties().put("PID", sysPid);
        }
    }
    public static final String CLIENT = "client";
    public static final String SERVER = "server";
    protected String side;

    protected String applicationName;
    protected String applicationId;

    protected int socketBacklog;
    protected int socketRecvBufSize;
    protected int socketSendBufSize;
    protected int frameMaxLength;

    protected final List<RpcController> rpcControllers;

    protected LogLevel nettyLoggingLevel;

    protected int readTimeout;

    protected boolean ordered;

    protected List<ConnectionListener> connectionListeners;

    public AbstractConfig(String side) {
        this.side = side;
        rpcControllers = new ArrayList<>();
        connectionListeners = new ArrayList<>();
    }

    @Override
    public List<RpcController> getRpcControllers() {
        return Collections.unmodifiableList(rpcControllers);
    }

    public void addRpcControllers(List<RpcController> rpcControllers) {
        if (rpcControllers == null || rpcControllers.isEmpty()) {
            return;
        }
        this.rpcControllers.addAll(rpcControllers);
    }

    @Override
    public String getApplicationName() {
        return applicationName;
    }

    public void setApplicationName(String applicationName) {
        this.applicationName = applicationName;
    }

    @Override
    public String getApplicationId() {
        return applicationId;
    }

    public void setApplicationId(String applicationId) {
        this.applicationId = applicationId;
    }

    @Override
    public int getSocketBacklog() {
        return socketBacklog;
    }

    public void setSocketBacklog(int socketBacklog) {
        this.socketBacklog = socketBacklog;
    }

    @Override
    public int getSocketRecvBufSize() {
        return socketRecvBufSize;
    }

    public void setSocketRecvBufSize(int socketRecvBufSize) {
        this.socketRecvBufSize = socketRecvBufSize;
    }

    @Override
    public int getSocketSendBufSize() {
        return socketSendBufSize;
    }

    public void setSocketSendBufSize(int socketSendBufSize) {
        this.socketSendBufSize = socketSendBufSize;
    }

    @Override
    public int getFrameMaxLength() {
        return frameMaxLength;
    }

    public void setFrameMaxLength(int frameMaxLength) {
        this.frameMaxLength = frameMaxLength;
    }

    @Override
    public LogLevel getNettyLoggingLevel() {
        return nettyLoggingLevel;
    }

    public void setNettyLoggingLevel(LogLevel nettyLoggingLevel) {
        this.nettyLoggingLevel = nettyLoggingLevel;
    }

    @Override
    public int getReadTimeout() {
        return readTimeout;
    }

    public void setReadTimeout(int readTimeout) {
        this.readTimeout = readTimeout;
    }

    @Override
    public boolean isOrdered() {
        return ordered;
    }

    public void setOrdered(boolean ordered) {
        this.ordered = ordered;
    }

    public List<ConnectionListener> getConnectionListeners() {
        return Collections.unmodifiableList(connectionListeners);
    }

    public void addConnectionListeners(List<ConnectionListener> listeners) {
        if (listeners == null) {
            listeners = new ArrayList<>();
        }
        this.connectionListeners.addAll(listeners);
    }
}
